package org.jeecg.modules.extbpm.process.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.bpm.service.ActivitiService;
import org.jeecg.modules.bpm.util.BpmUtil;
import org.jeecg.modules.extbpm.process.common.WorkFlowGlobals;
import org.jeecg.modules.extbpm.process.entity.ExtActFlowData;
import org.jeecg.modules.extbpm.process.entity.ExtActProcessNode;
import org.jeecg.modules.extbpm.process.entity.ExtActProcessNodeDeployment;
import org.jeecg.modules.extbpm.process.entity.ExtActProcessNodePermission;
import org.jeecg.modules.extbpm.process.pojo.BizTaskDTO;
import org.jeecg.modules.extbpm.process.service.IExtActFlowDataService;
import org.jeecg.modules.extbpm.process.service.IExtActProcessNodeDeploymentService;
import org.jeecg.modules.extbpm.process.service.IExtActProcessNodePermissionService;
import org.jeecg.modules.extbpm.process.service.IExtActProcessNodeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

 /**
 * @Title: Controller
 * @Description: 流程节点表
 * @author： jeecg-boot
 * @date：   2019-03-15
 * @version： V1.0
 */
@RestController("extActProcessNodeController")
@RequestMapping("/act/process/extActProcessNode")
@Slf4j
public class ExtActProcessNodeController {
	@Autowired
	private IExtActProcessNodeService extActProcessNodeService;
	@Autowired
	private ActivitiService activitiService;
	@Autowired
	private TaskService taskService;
	@Autowired
	private RuntimeService runtimeService;
	@Autowired
	protected RepositoryService repositoryService;
	@Autowired
	private IExtActProcessNodeDeploymentService extActProcessNodeDeploymentService;
	@Autowired
	private IExtActProcessNodePermissionService extActProcessNodePermissionService;
	@Autowired
	private IExtActFlowDataService extActFlowDataService;
	
	/**
	  * 分页列表查询
	 * @param extActProcessNode
	 * @param pageNo
	 * @param pageSize
	 * @param req
	 * @return
	 */
	@GetMapping(value = "/list")
	public Result<IPage<ExtActProcessNode>> queryPageList(ExtActProcessNode extActProcessNode,
									  @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
									  @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
									  HttpServletRequest req) {
		Result<IPage<ExtActProcessNode>> result = new Result<IPage<ExtActProcessNode>>();
		QueryWrapper<ExtActProcessNode> queryWrapper = new QueryWrapper<ExtActProcessNode>(extActProcessNode);
		Page<ExtActProcessNode> page = new Page<ExtActProcessNode>(pageNo,pageSize);
		//排序逻辑
		queryWrapper.orderByAsc("process_node_code");
		IPage<ExtActProcessNode> pageList = extActProcessNodeService.page(page, queryWrapper);
		result.setSuccess(true);
		result.setResult(pageList);
		return result;
	}
	
	/**
	  *   添加
	 * @param extActProcessNode
	 * @return
	 */
	@PostMapping(value = "/add")
	public Result<ExtActProcessNode> add(@RequestBody ExtActProcessNode extActProcessNode) {
		Result<ExtActProcessNode> result = new Result<ExtActProcessNode>();
		try {
			extActProcessNodeService.save(extActProcessNode);
			result.success("添加成功！");
		} catch (Exception e) {
			log.error(e.getMessage(),e);
			result.error500("操作失败");
		}
		return result;
	}
	
	/**
	  *  编辑
	 * @param extActProcessNode
	 * @return
	 */
	@PutMapping(value = "/edit")
	public Result<?> edit(@RequestBody ExtActProcessNode extActProcessNode) {
		Result<ExtActProcessNode> result = new Result<ExtActProcessNode>();
		extActProcessNodeService.updateById(extActProcessNode);
		return Result.ok("编辑成功");
	}
	
	/**
	  *   通过id删除
	 * @param id
	 * @return
	 */
	@DeleteMapping(value = "/delete")
	public Result<ExtActProcessNode> delete(@RequestParam(name="id",required=true) String id) {
		Result<ExtActProcessNode> result = new Result<ExtActProcessNode>();
		ExtActProcessNode extActProcessNode = extActProcessNodeService.getById(id);
		if(extActProcessNode==null) {
			result.error500("未找到对应实体");
		}else {
			boolean ok = extActProcessNodeService.removeById(id);
			if(ok) {
				result.success("删除成功!");
			}
		}
		
		return result;
	}
	
	/**
	  *  批量删除
	 * @param ids
	 * @return
	 */
	@DeleteMapping(value = "/deleteBatch")
	public Result<ExtActProcessNode> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
		Result<ExtActProcessNode> result = new Result<ExtActProcessNode>();
		if(ids==null || "".equals(ids.trim())) {
			result.error500("参数不识别！");
		}else {
			this.extActProcessNodeService.removeByIds(Arrays.asList(ids.split(",")));
			result.success("删除成功!");
		}
		return result;
	}
	
	/**
	  * 通过id查询
	 * @param id
	 * @return
	 */
	@GetMapping(value = "/queryById")
	public Result<ExtActProcessNode> queryById(@RequestParam(name="id",required=true) String id) {
		Result<ExtActProcessNode> result = new Result<ExtActProcessNode>();
		ExtActProcessNode extActProcessNode = extActProcessNodeService.getById(id);
		if(extActProcessNode==null) {
			result.error500("未找到对应实体");
		}else {
			result.setResult(extActProcessNode);
			result.setSuccess(true);
		}
		return result;
	}
	
	/**
	 *	根据流程实例id和任务id查询任务节点信息
	 * @param id
	 * @return
	 */
	@GetMapping(value = "/getProcessNodeInfo")
	public Result<Map<String,Object>> getProcessNodeInfo(@RequestParam(name="taskId",required=true) String taskId) {
		Result<Map<String,Object>> result = new Result<Map<String,Object>>();
		Task  task = activitiService.getTask(taskId);
		//获取流程定义ID
		String insId = task.getProcessInstanceId();
		Map<String,Object> variablesMap = runtimeService.getVariables(insId);
		String tableName = (String)variablesMap.get(WorkFlowGlobals.BPM_FORM_KEY);
		String dataId = (String)variablesMap.get(WorkFlowGlobals.BPM_DATA_ID);
		if(oConvertUtils.isEmpty(dataId)) {
			dataId = (String)variablesMap.get("id");
			runtimeService.setVariable(insId,WorkFlowGlobals.BPM_DATA_ID, dataId);
		}
		String processDefinitionId = task.getProcessDefinitionId();
		ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
		variablesMap.put("BPM_TASK_KEY", task.getTaskDefinitionKey());
		variablesMap.put("BPM_TASK_ID", taskId);
		variablesMap.put("BPM_INST_ID", insId);
		variablesMap.put("BPM_PROC_DEF_ID", processDefinitionId);

		//a.获取节点表单配置
		String defautformUrl = (String)variablesMap.get(WorkFlowGlobals.BPM_FORM_CONTENT_URL);
		String defautformUrlMobile = (String)variablesMap.get(WorkFlowGlobals.BPM_FORM_CONTENT_URL_MOBILE);
		//a.1 如果没有默认地址，去开始节点配置的地址
		if(oConvertUtils.isEmpty(defautformUrl) || oConvertUtils.isEmpty(defautformUrlMobile)) {
			LambdaQueryWrapper<ExtActProcessNodeDeployment> queryWrapper = new LambdaQueryWrapper<ExtActProcessNodeDeployment>();
			queryWrapper.eq(ExtActProcessNodeDeployment::getProcessNodeCode, WorkFlowGlobals.BPM_NODE_START);
			queryWrapper.eq(ExtActProcessNodeDeployment::getDeploymentId, processDefinition.getDeploymentId());
			ExtActProcessNodeDeployment node = extActProcessNodeDeploymentService.getOne(queryWrapper);
			if(node!=null&&oConvertUtils.isNotEmpty(node.getModelAndView())) {
				defautformUrl = BpmUtil.getNodeUrl(variablesMap, node.getModelAndView(), dataId);
				runtimeService.setVariable(insId,WorkFlowGlobals.BPM_FORM_CONTENT_URL, defautformUrl);
			}
			if(node!=null&&oConvertUtils.isNotEmpty(node.getModelAndViewMobile())) {
				defautformUrlMobile = BpmUtil.getNodeUrl(variablesMap, node.getModelAndViewMobile(), dataId);
				runtimeService.setVariable(insId,WorkFlowGlobals.BPM_FORM_CONTENT_URL_MOBILE, defautformUrlMobile);
			}
		}

		//a.2 获取节点的表单地址配置（PC地址 + 移动地址）
		LambdaQueryWrapper<ExtActProcessNodeDeployment> queryWrapper = new LambdaQueryWrapper<ExtActProcessNodeDeployment>();
		queryWrapper.eq(ExtActProcessNodeDeployment::getProcessNodeCode, task.getTaskDefinitionKey());
		queryWrapper.eq(ExtActProcessNodeDeployment::getDeploymentId, processDefinition.getDeploymentId());
		ExtActProcessNodeDeployment node = extActProcessNodeDeploymentService.getOne(queryWrapper);
		if(node!=null&&oConvertUtils.isNotEmpty(node.getModelAndView())) {
			//节点地址表达式解析
			defautformUrl = BpmUtil.getNodeUrl(variablesMap, node.getModelAndView(), dataId);
		}
		if(node!=null&&oConvertUtils.isNotEmpty(node.getModelAndViewMobile())) {
			//节点地址表达式解析
			defautformUrlMobile = BpmUtil.getNodeUrl(variablesMap, node.getModelAndViewMobile(), dataId);
		}

		//b.获取节点权限配置
		List<Map<String,Object>> permissionList = new ArrayList<Map<String,Object>>();
		if(node!=null) {
			LambdaQueryWrapper<ExtActProcessNodePermission> queryAuthWrapper = new LambdaQueryWrapper<ExtActProcessNodePermission>();
			queryAuthWrapper.eq(ExtActProcessNodePermission::getProcessId, node.getProcessId());
			queryAuthWrapper.eq(ExtActProcessNodePermission::getProcessNodeCode, node.getProcessNodeCode());
			queryAuthWrapper.eq(ExtActProcessNodePermission::getStatus, "1");
			queryAuthWrapper.eq(ExtActProcessNodePermission::getFormType, WorkFlowGlobals.BPM_FORM_TYPE_3);
			if(oConvertUtils.isNotEmpty(tableName)){
				queryAuthWrapper.eq(ExtActProcessNodePermission::getFormBizCode, tableName);
			}
			List<ExtActProcessNodePermission> list = extActProcessNodePermissionService.list(queryAuthWrapper);
			Map<String,Object> permissionmap = null;
			for(ExtActProcessNodePermission auth:list) {
				permissionmap = new HashMap<String,Object>();
				permissionmap.put("action", auth.getRuleCode());
				permissionmap.put("type", auth.getRuleType());
				permissionList.add(permissionmap);
			}
		}

		//c.返回节点相关配置
		Map<String,Object> map = new HashMap<String,Object>();
		map.put("formUrl", defautformUrl);
		map.put("formUrlMobile", defautformUrlMobile);
		map.put("taskId", taskId);
		map.put("taskDefKey", task.getTaskDefinitionKey());
		map.put("dataId", dataId);
		map.put("tableName", tableName);
		map.put("permissionList", permissionList);
		map.put("records", variablesMap);
		result.setResult(map);
		result.setSuccess(true);
		return result;
	}
	
	/**
	 *	根据流程实例id和任务id查询任务节点信息
	 * @param id
	 * @return
	 */
	@GetMapping(value = "/getHisProcessNodeInfo")
	public Result<Map<String,Object>> getHisProcessNodeInfo(@RequestParam(name="procInstId",required=true) String procInstId) {
		Result<Map<String,Object>> result = new Result<Map<String,Object>>();
		
		//获取流程定义ID
		String formUrl = activitiService.getHisVarinst(WorkFlowGlobals.BPM_FORM_CONTENT_URL,procInstId);
		String formUrlMobile = activitiService.getHisVarinst(WorkFlowGlobals.BPM_FORM_CONTENT_URL_MOBILE,procInstId);
		String dataId = activitiService.getHisVarinst(WorkFlowGlobals.BPM_DATA_ID,procInstId);
		String tableName = activitiService.getHisVarinst(WorkFlowGlobals.BPM_FORM_KEY,procInstId);
		Map<String,Object> variablesMap = new HashMap<String,Object>();
		variablesMap.put(WorkFlowGlobals.BPM_DATA_ID, dataId);
		variablesMap.put(WorkFlowGlobals.BPM_FORM_KEY, tableName);
		Map<String,Object> map = new HashMap<String,Object>();
		map.put("formUrl", formUrl);
		map.put("formUrlMobile", formUrlMobile);
		map.put("taskId", "");
		map.put("taskDefKey", "");
		map.put("dataId", dataId);
		map.put("tableName", tableName);
		map.put("permissionList", new ArrayList<Map<String,Object>>());
		map.put("records", variablesMap);
		result.setResult(map);
		result.setSuccess(true);
		return result;
	}
	
	
	/**
	 *	根据流程编码和业务key查询任务节点信息,查询我的待办任务
	 * @param id
	 * @return
	 */
	@GetMapping(value = "/getBizProcessNodeInfo")
	public Result<Map<String,Object>> getBizProcessNodeInfo(@RequestParam(name="flowCode",required=true) String flowCode,
			@RequestParam(name="dataId",required=true) String bizKey,HttpServletRequest req) {
		
		Result<Map<String,Object>> result = new Result<Map<String,Object>>();
		//根据流程编码和业务key查询流程实例id
		LambdaQueryWrapper<ExtActFlowData> queryWrapperD = new LambdaQueryWrapper<ExtActFlowData>();
		queryWrapperD.eq(ExtActFlowData::getRelationCode, flowCode);
		queryWrapperD.eq(ExtActFlowData::getFormDataId, bizKey);
		ExtActFlowData extActFlowData = extActFlowDataService.getOne(queryWrapperD);
		if(extActFlowData==null) {
			result.error500("未找到对应实体");
		}else {
			//获取流程定义ID
			String insId = extActFlowData.getProcessInstId();
			Map<String,Object> variablesMap = runtimeService.getVariables(insId);
			String dataId = extActFlowData.getFormDataId();
			ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(insId).singleResult();
			//根据流程实例id查询当前我的待办任务
			String userid = JwtUtil.getUserNameByToken(req); // 获取当前登录用户
			String taskId = "";
			List<Task> userTaskList = taskService.createTaskQuery()//创建查询对象
					.processInstanceId(extActFlowData.getProcessInstId())
					.taskAssignee(userid)//指定查询人
					.list();
			List<Task> groupTaskList = taskService.createTaskQuery()//创建查询对象
					.processInstanceId(extActFlowData.getProcessInstId())
					.taskCandidateUser(userid)//参与者，组任务查询
					.list();
			List<BizTaskDTO> bizTaskList = this.getBizTaskDTOs(userTaskList, groupTaskList,processInstance);
//			Task  task = activitiService.getTask(taskId);
			BizTaskDTO task = bizTaskList.get(0);
			taskId = task.getTaskId();
			String processDefinitionId =processInstance.getProcessDefinitionId();
			
//			String processDefinitionId = task.getProcDefId();
//			ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
			variablesMap.put("BPM_TASK_ID", taskId);
			variablesMap.put("BPM_INST_ID", taskId);
			variablesMap.put("BPM_PROC_DEF_ID", processDefinitionId);
			
			String defautformUrl = (String)variablesMap.get(WorkFlowGlobals.BPM_FORM_CONTENT_URL);
			//如果没有默认地址，去开始节点配置的地址
			if(oConvertUtils.isEmpty(defautformUrl)) {
				LambdaQueryWrapper<ExtActProcessNodeDeployment> queryWrapper = new LambdaQueryWrapper<ExtActProcessNodeDeployment>();
				queryWrapper.eq(ExtActProcessNodeDeployment::getProcessNodeCode, WorkFlowGlobals.BPM_NODE_START);
				queryWrapper.eq(ExtActProcessNodeDeployment::getDeploymentId, processInstance.getDeploymentId());
				ExtActProcessNodeDeployment node = extActProcessNodeDeploymentService.getOne(queryWrapper);
				if(node!=null&&oConvertUtils.isNotEmpty(node.getModelAndView())) {
					String startUrl = BpmUtil.getNodeUrl(variablesMap, node.getModelAndView(), dataId);
					defautformUrl = startUrl;
					runtimeService.setVariable(insId,WorkFlowGlobals.BPM_FORM_CONTENT_URL, startUrl);
				}
			}
			
			String formUrl = "";
			LambdaQueryWrapper<ExtActProcessNodeDeployment> queryWrapper = new LambdaQueryWrapper<ExtActProcessNodeDeployment>();
			queryWrapper.eq(ExtActProcessNodeDeployment::getProcessNodeCode, task.getTaskId());
			queryWrapper.eq(ExtActProcessNodeDeployment::getDeploymentId, processInstance.getDeploymentId());
			ExtActProcessNodeDeployment node = extActProcessNodeDeploymentService.getOne(queryWrapper);
			if(node!=null&&oConvertUtils.isNotEmpty(node.getModelAndView())) {
				formUrl =  node.getModelAndView();
				//节点地址表达式解析
				formUrl = BpmUtil.getNodeUrl(variablesMap, formUrl, dataId);
				defautformUrl = formUrl;
			}
			
			List<Map<String,Object>> permissionList = new ArrayList<Map<String,Object>>();
			if(node!=null) {
				LambdaQueryWrapper<ExtActProcessNodePermission> queryAuthWrapper = new LambdaQueryWrapper<ExtActProcessNodePermission>();
				queryAuthWrapper.eq(ExtActProcessNodePermission::getProcessId, node.getProcessId());
				queryAuthWrapper.eq(ExtActProcessNodePermission::getProcessNodeCode, node.getProcessNodeCode());
				queryAuthWrapper.eq(ExtActProcessNodePermission::getStatus, "1");
				List<ExtActProcessNodePermission> list = extActProcessNodePermissionService.list(queryAuthWrapper);
				Map<String,Object> permissionmap = null;
				for(ExtActProcessNodePermission auth:list) {
					permissionmap = new HashMap<String,Object>();
					permissionmap.put("action", auth.getRuleCode());
					permissionmap.put("type", auth.getRuleType());
					permissionList.add(permissionmap);
				}
				
			}
			
			Map<String,Object> map = new HashMap<String,Object>();
			map.put("formUrl", defautformUrl);
			map.put("taskId", task.getId());
			map.put("taskDefKey", task.getTaskId());
			map.put("dataId", dataId);
			map.put("procInsId", extActFlowData.getProcessInstId());
			map.put("tableName", extActFlowData.getFormTableName());
			map.put("permissionList", permissionList);
			map.put("bizTaskList", bizTaskList);
			map.put("records", variablesMap);
			result.setResult(map);
			result.setSuccess(true);
		}
		
		
		return result;
	}
	
	private List<BizTaskDTO> getBizTaskDTOs(List<Task> userTaskList,List<Task> groupTaskList,ProcessInstance processInstance){
		List<BizTaskDTO> bizTaskList = new ArrayList<BizTaskDTO>();
		BizTaskDTO bizTask = null;
		for(Task task:userTaskList) {
			bizTask = new BizTaskDTO();
			bizTask.setId(task.getId());
			bizTask.setTaskId(task.getTaskDefinitionKey());
			bizTask.setTaskName(task.getName());
			bizTask.setTaskClaimFlag(false);
			bizTask.setProcDefId(task.getProcessDefinitionId());
			bizTask.setSuspendFlag(processInstance.isSuspended());
			bizTask.setProcInstId(processInstance.getProcessInstanceId());
			bizTaskList.add(bizTask);
		}
		for(Task task:groupTaskList) {
			bizTask = new BizTaskDTO();
			bizTask.setId(task.getId());
			bizTask.setTaskId(task.getTaskDefinitionKey());
			bizTask.setTaskName(task.getName());
			if(oConvertUtils.isEmpty(task.getAssignee())) {
				bizTask.setTaskClaimFlag(true);
			}else {
				bizTask.setTaskClaimFlag(false);
			}
			bizTask.setProcDefId(task.getProcessDefinitionId());
			bizTask.setSuspendFlag(processInstance.isSuspended());
			bizTask.setProcInstId(processInstance.getProcessInstanceId());
			bizTaskList.add(bizTask);
		}
		return bizTaskList;
	}
	
	/**
	 *	根据流程实例id和任务id查询任务节点信息
	 * @param id
	 * @return
	 */
	@GetMapping(value = "/getBizHisProcessNodeInfo")
	public Result<Map<String,Object>> getBizHisProcessNodeInfo(@RequestParam(name="flowCode",required=true) String flowCode,
			@RequestParam(name="dataId",required=true) String bizKey,HttpServletRequest req) {
		Result<Map<String,Object>> result = new Result<Map<String,Object>>();
		//根据流程编码和业务key查询流程实例id
		LambdaQueryWrapper<ExtActFlowData> queryWrapperD = new LambdaQueryWrapper<ExtActFlowData>();
		queryWrapperD.eq(ExtActFlowData::getRelationCode, flowCode);
		queryWrapperD.eq(ExtActFlowData::getFormDataId, bizKey);
		ExtActFlowData extActFlowData = extActFlowDataService.getOne(queryWrapperD);
		//获取流程定义ID
		String formUrl = activitiService.getHisVarinst(WorkFlowGlobals.BPM_FORM_CONTENT_URL,extActFlowData.getProcessInstId());
		String dataId = bizKey;
		String tableName = extActFlowData.getFormTableName();
		Map<String,Object> variablesMap = new HashMap<String,Object>();
		variablesMap.put(WorkFlowGlobals.BPM_DATA_ID, dataId);
		variablesMap.put(WorkFlowGlobals.BPM_FORM_KEY, tableName);
		Map<String,Object> map = new HashMap<String,Object>();
		map.put("formUrl", formUrl);
		map.put("taskId", "");
		map.put("taskDefKey", "");
		map.put("dataId", dataId);
		map.put("procInsId", extActFlowData.getProcessInstId());
		map.put("tableName", tableName);
		map.put("permissionList", new ArrayList<Map<String,Object>>());
		map.put("bizTaskList", new ArrayList<BizTaskDTO>());
		map.put("records", variablesMap);
		result.setResult(map);
		result.setSuccess(true);
		return result;
	}

}
